package com.hitqz.robot.biz.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.cache.Cache;
import com.hitqz.robot.api.business.dto.RobotAddDispatchDto;
import com.hitqz.robot.api.business.dto.RobotClientSummaryDto;
import com.hitqz.robot.api.business.dto.RobotEquipmentPanelDto;
import com.hitqz.robot.api.business.dto.RobotStatusDto;
import com.hitqz.robot.api.business.entity.RobotEntity;
import com.hitqz.robot.api.business.entity.RobotGroupEntity;
import com.hitqz.robot.api.business.entity.RobotMapEntity;
import com.hitqz.robot.api.business.vo.LogRobotListVo;
import com.hitqz.robot.api.business.vo.RobotLiveAddressVo;
import com.hitqz.robot.api.business.vo.RobotVo;
import com.hitqz.robot.biz.service.RobotGroupService;
import com.hitqz.robot.biz.service.RobotMapService;
import com.hitqz.robot.biz.service.RobotService;
import com.hitqz.robot.common.core.util.R;
import com.hitqz.robot.common.log.annotation.SysLog;
import com.hitqz.robot.common.security.service.RobotUser;
import com.hitqz.robot.common.security.util.SecurityUtils;
import com.pig4cloud.plugin.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 机器人管理表
 *
 * @author robot
 * @date 2024-06-06 15:18:09
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/robot" )
@Tag(description = "robot" , name = "机器人管理表管理" )
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class RobotController {


    private final RobotService robotService;

	private final RobotGroupService robotGroupService;

	private final RobotMapService robotMapService;



	@Operation(summary = "查询在线机器人数据" , description = "查询在线机器人数据" )
	@GetMapping(value = "onlineRobot")
	public R<List<RobotEntity>> getOnlineRobot() {
		Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
		List<RobotEntity> robotEntityList =  Lists.newArrayList();
		for (String robotSn : CollUtil.emptyIfNull(posInfoDtoCache.asMap().keySet())) {
			robotEntityList.add(robotService.selectByRobotSn(robotSn));
		}
		return R.ok(robotEntityList);
	}


	@Operation(summary = "查询所有机器人数据" , description = "查询所有机器人数据" )
	@GetMapping(value = "list")
	public R<List<RobotEntity>> list() {
		List<RobotEntity> robotEntityList =  robotService.list();
		return R.ok(robotEntityList);
	}



    /**
     * 分页查询
     * @param page 分页对象
     * @param robot 机器人管理表
     * @return
     */
    @Operation(summary = "分页查询" , description = "分页查询" )
    @GetMapping("/page" )
    public R<Page<RobotVo>> getRobotPage(@ParameterObject Page page, @ParameterObject RobotEntity robot) {
        LambdaQueryWrapper<RobotEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(robot.getGroupId()!=null, RobotEntity::getGroupId, robot.getGroupId()==null?null:Math.abs(robot.getGroupId()));
        wrapper.eq(StrUtil.isNotBlank(robot.getMapCode()), RobotEntity::getMapCode, robot.getMapCode());
        wrapper.eq(robot.getId()!=null, RobotEntity::getId, robot.getId());
        wrapper.like(StrUtil.isNotBlank(robot.getRobotName()), RobotEntity::getRobotName, robot.getRobotName());
        wrapper.eq(StrUtil.isNotBlank(robot.getRobotSn()), RobotEntity::getRobotSn, robot.getRobotSn());
		Page<RobotEntity> pageData = robotService.page(page, wrapper);
		Map<Integer, String> groupMap = robotGroupService.list().stream().collect(Collectors.toMap(RobotGroupEntity::getId, RobotGroupEntity::getName));
		Page<RobotVo> voPage = new Page<>(page.getCurrent(), page.getSize());
		voPage.setTotal(pageData.getTotal());
		List<RobotVo> robotVos = Lists.newArrayList();
		Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
		for (RobotEntity record : CollUtil.emptyIfNull(pageData.getRecords())) {
			RobotVo robotVo = new RobotVo();
			BeanUtil.copyProperties(record, robotVo);
			robotVo.setGroupName(groupMap.get(record.getGroupId()));
			RobotMapEntity robotMap = robotMapService.findByMapCode(record.getMapCode());
			robotVo.setMapName(robotMap != null ? robotMap.getMapName(): robot.getMapCode());
			String onlineStatusStr = Optional.ofNullable(posInfoDtoCache.getIfPresent(record.getRobotSn())).map(RobotClientSummaryDto::getStatus).map(RobotStatusDto::getOnlineStatusStr).orElse("离线");
			robotVo.setOnlineStatusStr(onlineStatusStr);
			robotVos.add(robotVo);
		}
		voPage.setRecords(robotVos);
		return R.ok(voPage);
    }

	/**
	 * 返回树形机器人集合
	 * @return 树形菜单
	 */
	@Operation(summary = "获取树状结构" , description = "获取树状结构" )
	@GetMapping(value = "/tree")
	public R getTree() {
		RobotUser user = SecurityUtils.getUser();
		return R.ok(robotService.selectTree(user));
	}


    /**
     * 通过id查询机器人管理表
     * @param id id
     * @return R
     */
    @Operation(summary = "通过id查询" , description = "通过id查询" )
    @GetMapping("/{id}" )
    public R<RobotEntity> getById(@PathVariable("id" ) Integer id) {
		RobotEntity robot = robotService.getById(id);
		if (robot!=null  && robot.getGroupId()> 0){
			RobotGroupEntity group = robotGroupService.getById(robot.getGroupId());
			robot.setGroupName(group.getName());
		}else {
			robot.setGroupId(1);
		}
		return R.ok(robot);
    }

    /**
     * 新增机器人管理表
     * @param robot 机器人管理表
     * @return R
     */
    @Operation(summary = "新增机器人管理表" , description = "新增机器人管理表" )
    @SysLog("新增机器人管理表" )
    @PostMapping
	@CacheEvict(cacheNames = "robot::client", key = "#robot.robotSn")
    public R save(@RequestBody RobotEntity robot) {
		if (robot.getGroupId()!=null) {
			robot.setGroupId(Math.abs(robot.getGroupId()));
		}
        return R.ok(robotService.save(robot));
    }

    /**
     * 修改机器人管理表
     * @param robot 机器人管理表
     * @return R
     */
    @Operation(summary = "修改机器人管理表" , description = "修改机器人管理表" )
    @SysLog("修改机器人管理表" )
    @PutMapping
	@CacheEvict(cacheNames = "robot::client", key = "#robot.robotSn")
    public R updateById(@RequestBody RobotEntity robot) {
		if (robot.getGroupId()!=null) {
			robot.setGroupId(Math.abs(robot.getGroupId()));
		}
		RobotEntity robotEntity = robotService.selectByRobotSn(robot.getRobotSn());
		Integer oldGroupId = robotEntity.getGroupId();
		Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
		RobotClientSummaryDto robotClientSummaryDto = posInfoDtoCache.getIfPresent(robotEntity.getRobotSn());
		if (robotClientSummaryDto == null) {
			return R.failed("机器人不在线无法操作");
		}
		SpringUtil.getApplicationContext().publishEvent(robot);
		RobotAddDispatchDto robotAddDispatchDto = new RobotAddDispatchDto();
		robotAddDispatchDto.setRobotSn(robot.getRobotSn());
		robotAddDispatchDto.setOldGroupId(oldGroupId);
		//先修改数据库
		robotService.updateById(robot);
		//修改缓存
		SpringUtil.getApplicationContext().publishEvent(robotAddDispatchDto);
        return R.ok();
    }

    /**
     * 通过id删除机器人管理表
     * @param ids id列表
     * @return R
     */
    @Operation(summary = "通过id删除机器人管理表" , description = "通过id删除机器人管理表" )
    @SysLog("通过id删除机器人管理表" )
    @DeleteMapping
	@CacheEvict(cacheNames = "robot::client", key = "#robot.robotSn")
    public R removeById(@RequestBody Integer[] ids) {
        return R.ok(robotService.removeBatchByIds(CollUtil.toList(ids)));
    }


    /**
     * 导出excel 表格
     * @param robot 查询条件
   	 * @param ids 导出指定ID
     * @return excel 文件流
     */
    @ResponseExcel
    @GetMapping("/export")
    public List<RobotEntity> export(RobotEntity robot, Integer[] ids) {
        return robotService.list(Wrappers.lambdaQuery(robot).in(ArrayUtil.isNotEmpty(ids), RobotEntity::getId, ids));
    }




	@Operation(summary = "获取机器人相机相关外设播放地址" )
	@SysLog("获取机器人相机相关外设播放地址" )
	@GetMapping(value = "getLiveAddress")
	public R<List<RobotLiveAddressVo>> getLiveAddress(@RequestParam(value = "robotSn") String robotSn) {
		RobotEntity robotEntity = robotService.selectByRobotSn(robotSn);
		Integer oldGroupId = robotEntity.getGroupId();
		Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
		RobotClientSummaryDto robotClientSummaryDto = posInfoDtoCache.getIfPresent(robotEntity.getRobotSn());
		if (robotClientSummaryDto == null) {
			return R.failed("机器人不在线无法操作");
		}
		List<RobotLiveAddressVo> robotLiveAddressVos = Lists.newArrayList();
		RobotEquipmentPanelDto panelDtos = robotClientSummaryDto.getEquipmentPanel();

		if (CollUtil.isEmpty(panelDtos.getPlayUrls())) {
			return R.failed("暂无可查看视频");
		}
		for (String liveAddress : panelDtos.getPlayUrls()) {
			RobotLiveAddressVo robotLiveAddressVo = new RobotLiveAddressVo();
			robotLiveAddressVo.setLiveAddress(liveAddress);
			robotLiveAddressVos.add(robotLiveAddressVo);
		}
		return R.ok(robotLiveAddressVos);
	}



	@Operation(summary = "可获取的日志列表" )
	@SysLog("可获取的日志列表" )
	@GetMapping(value = "getLogRobotList")
	public R<List<LogRobotListVo>> getLogRobotList() {
		List<LogRobotListVo> logRobotListVos = Lists.newArrayList();
		LogRobotListVo logRobotListVo = new LogRobotListVo();
		logRobotListVo.setLabel("系统日志");
		logRobotListVo.setValue("server");
		logRobotListVos.add(logRobotListVo);
		Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
		for (RobotClientSummaryDto robotClientSummaryDto : posInfoDtoCache.asMap().values()) {
			LogRobotListVo listVo = new LogRobotListVo();
			listVo.setValue(robotClientSummaryDto.getClientId());
			listVo.setLabel(robotService.selectByRobotSn(robotClientSummaryDto.getClientId()).getRobotName());
			logRobotListVos.add(listVo);
		}
		return R.ok(logRobotListVos);
	}


}